feat(discovery): mesh network discovery#5275
Conversation
7a61af0 to
c213146
Compare
891becc to
0335907
Compare
515ca60 to
48c58f3
Compare
🖼️ Preview staleness check — advisoryThis PR modifies UI composables but does not update any
Changed UI files: What to check:
Adding previews checklist:
If this PR does not require preview updates (e.g., logic-only change, non-visual refactor), add the |
Squash merge of PR #5275 into release/2.8.0. Adds Local Mesh Discovery feature with multi-preset scanning, topology visualization, and historical session management. Includes DiscoveryScanEngine, database schema v39 with discovery tables, flavor-specific map views, and real-time scan progress UI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔗 Release 2.8.0 Integration ReportBranch: Integration Changes Required (Most Extensive)This PR required the most integration work due to its size (90 files) and touchpoints across database, maps, and service layers. Database Layer
Map Layer (androidApp flavor sources)
Feature Module
DI
Merge Guidance
|
* Introduce a new `:feature:discovery` module for scanning mesh topology across multiple LoRa presets * Add `DiscoveryScanEngine` to manage scan lifecycles, preset shifting, and packet collection * Update database schema to version 39 with tables for discovery sessions, preset results, and discovered nodes * Implement UI screens for scan configuration, real-time progress, and historical session management * Add flavor-specific discovery maps (Google Maps and OSM) for visualizing node positions and topology * Include algorithmic and AI-powered summary generation for analyzing LoRa preset performance * Add report export functionality for Text and PDF formats * Integrate discovery entry point into the settings screen and navigation graphs
…tion restoration - Implement distance tracking using `latLongToMeter` and a new `getMaxDistance` DAO query - Calculate Airtime Rate as a delta over time to align with telemetry specifications - Capture and restore the full `LoRaConfig` instead of just the modem preset after a scan - Persist local radio statistics (Tx/Rx counts, uptime, relay stats) in preset results - Backfill missing node names and positions from the local NodeDB during discovery - Refactor `DiscoveryScanEngine` to use injected `CoroutineDispatchers` and `ApplicationCoroutineScope` - Reduce BLE connection priority request delay in `BleRadioTransport` to 1 second - Improve test reliability by replacing fixed `Thread.sleep` calls with state-based polling and `delay`
- Replace platform-specific `String.format` with Kotlin standard library `padStart` in `DwellProgressIndicator` to support common code. - Simplify fully qualified icon references in `DiscoveryGoogleMap` by adding explicit imports.
…ests - Add Preparing, Cancelling, Failed states to DiscoveryScanState (FR-008) - Change Complete to data class with CompletionOutcome enum - Add local-mesh-discovery deep link routes to DeepLinkRouter (FR-031) - Compute packetSuccessRate/packetFailureRate in scan engine (FR-012) - Fix DiscoveryScanEngineTest compilation and restructure with shared scheduler - All 8 tests pass, kmpSmokeCompile clean
…c heuristic (D029) Implement the spec's ranking and recommendation heuristic: 1. Highest unique discovered node count 2. Highest neighbor-report diversity (direct + mesh) 3. Highest non-duplicate packet count 4. Best median link quality (SNR first, then RSSI) 5. Greatest best known distance 6. Lowest failure/reconnect penalty Presets tied after all 6 criteria share the same rank with isTied=true. Includes RankingScoreBreakdown for transparent per-criterion scoring. 11 unit tests covering each criterion as tiebreaker, full ties, edge cases (empty/single preset, no nodes, failed presets). Validated: spotlessApply, allTests, kmpSmokeCompile
Mark 30 of 49 tasks as complete based on code review of the feat/discovery branch. Key phases completed: setup (P1), data model (P2 partial), scan engine (P3), packet collection (P4 partial), map (P5 partial), summary (P6 partial), AI (P7 partial), history (P8). Remaining: D010-D011 (DAO/migration tests), D012 (prefs), D020 (neighbor info trigger), D023-D024 (tests + map filter), D028 (map UI tests), D030/D032 (summary models + tests), D037 (AI tests), D042 (history tests), D044-D045/D047-D048 (polish).
- Add rankings StateFlow to DiscoverySummaryViewModel - Compute rankings from PresetRankingInput on loadNodes and rerunAnalysis - Pass rank/isTied to PresetResultCard for display - Show rank badge (#1, #2, tied) in preset header - Rank 1 (untied) highlighted in primary color Validated: spotlessApply, allTests, compileKotlinJvm
Add DataStore-backed preferences for discovery scan settings: - dwellMinutes: persisted dwell time per preset (default 15) - selectedPresets: last-used preset selection (restored on reopen) - aiEnabled: whether AI summary expansion is enabled - topologyOverlayEnabled: map topology overlay default Architecture: - Interface: DiscoveryPrefs in core:repository/AppPreferences.kt - Implementation: DiscoveryPrefsImpl in core:prefs (reuses UiDataStore) - Fake: FakeDiscoveryPrefs in core:testing - Wiring: DiscoveryViewModel restores prefs on init, persists on change Validated: spotlessApply, allTests, compileKotlinJvm
- Use BundledSQLiteDriver in DatabaseBuilder for deterministic SQLite behavior across test environments - Simplify DiscoveryMigrationTest to use context-free inMemoryDatabaseBuilder with BundledSQLiteDriver (removes ApplicationProvider dependency) - Update migration doc comment to reflect version 39→40 path Found during release/2.8.0 integration testing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
55cdbec to
33bd343
Compare
📄 Docs staleness check — advisoryThis PR modifies user-facing UI source files but does not update any page under
Changed source files: What to check:
New page checklist (if adding a new doc page):
If this PR does not require a doc update (e.g., internal refactor, bug fix, test change), add the
|
❌ 9 Tests Failed:
View the top 3 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move discovery map files from orphaned app/ to androidApp/ flavors - Remove duplicate @Suppress annotation in MainActivity - Fix DeepLinkRouterTest: SettingsGraph -> Settings (renamed on main) - Fix MeshDataHandlerTest: add missing collectorRegistry parameter - Remove BundledSQLiteDriver from production DatabaseBuilder (API 26+ framework SQLite supports FTS5 natively) - Delete orphaned app/ directory (module renamed to androidApp/) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ve lib - Add ic_thermostat.xml and ic_person.xml to fdroid res/drawable for osmdroid marker icons (moved to compose resources on main) - Fix spotless formatting in DeepLinkRouterTest - Add sqlite-bundled-jvm runtimeOnly to core:database androidHostTest so BundledSQLiteDriver can load on the host JVM Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolved conflicts:
- Room schema renumbered v39 -> v42 (FTS5=39, air-quality=40, msh.to=41): version=42,
AutoMigration(41->42), 3 discovery entities, regenerated 42.json, kept release's 39.json
- MeshtasticDatabase imports: union Discovery{Dao,entities} + DeviceLink{Dao,Entity}
- SettingsScreen / DesktopSettingsScreen: union Discovery + DeviceLinks (+ AppFunctions) entries
- proto pinned to 6b1ded4 (master HEAD); docs: take release/2.8.0
Post-merge API fixups (#5586 AIDL removal):
- DiscoveryScanEngine: RadioController core.model -> core.repository; getPacketId() -> generatePacketId()
- discovery tests: DataPacket.ID_BROADCAST -> NodeAddress.ID_BROADCAST
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5275 created :feature:discovery with implementation(projects.core.proto), but main's #5675 replaced the :core:proto submodule with the org.meshtastic:protobufs Maven artifact. Rebasing left a stale module reference. Switched to implementation(libs.meshtastic.protobufs), matching the convention (cf. feature/node). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Local Mesh Discovery feature
:feature:discoverymodule for scanning mesh topology across multiple LoRa presetsDiscoveryScanEngineto manage scan lifecycles, preset shifting, and packet collection